package algorithms;

import java.util.List;
import java.util.Set;

import datastructures.DicHashTreeNode;
import datastructures.ItemSet;

/**
 * @author Yuval Kesten
 *         <ul>
 *         A variant of {@link Dic}. In this implementation we don't discover
 *         new item sets on the "stations" (every M baskets), every time we
 *         encounter a new item set which we haven't counted before. If its two
 *         sub sets of size-1 are frequent than we will start to count it on the
 *         fly.
 *         </ul>
 */
public class DicAlternative extends Dic {

	public DicAlternative(String pathFormat, int startIndex, int endIndex, int _M, Set<String> alphabetSet,
			int _estimatedNumOfBaskets) throws Exception {
		super(pathFormat, startIndex, endIndex, _M, alphabetSet, _estimatedNumOfBaskets);
	}

	@Override
	protected void pruneAndDiscover(double support) {
		hashTreeRoot.pruneAtDepth(this, support, estimatedNumOfBaskets, k, basketIndex);
		if (iterNum == 1 || k < maxBasketSize) {
			k++;
			kDiscoveryIndices.put(k, basketIndex);
		}
	}

	@Override
	protected void handleOneBasketPhase(String[] tmpBasket, int subsetsSize, DicHashTreeNode root, long basketIndex,
			double support) {
		List<List<String>> subsets = Common.getAllSubsets(tmpBasket, subsetsSize, getAlphabet());
		String word;
		if (subsets == null)
			return;
		DicHashTreeNode traverser;
		for (List<String> list : subsets) {
			traverser = root;
			if (traverser.childrens == null)
				continue;
			// assert(k==list.size());
			for (int i = 0; i < subsetsSize; i++) {
				word = list.get(i);
				if (traverser.childrens.containsKey(word)) {
					traverser = traverser.childrens.get(word);
					if (i == subsetsSize - 1) {
						traverser.encounterNode(basketIndex, estimatedNumOfBaskets, getSupportAsInt(support, i + 1),
								iterNum);
					}
				} else if (i == 0) {
					Algo.incStats(1);
					traverser = new DicHashTreeNode(1, basketIndex, word, root, iterNum, estimatedNumOfBaskets, support);
				} else {
					// This is the difference between this version of DIC and
					// the
					// original:
					DicHashTreeNode parent = traverser.parent;
					if (!parent.frequentChildrens.contains(traverser.keyAtPArent)) {
						break;
					}
					if (!parent.frequentChildrens.contains(word)) {
						break;
					}
					// Two good candidates - merge them!
					if (lastKWithDiscoveries < i + 1) {
						lastKWithDiscoveries = i + 1;
					}
					kDiscoveryIndices.put(i + 1, basketIndex);

					DicHashTreeNode node1 = traverser;
					ItemSet newIS = new ItemSet();
					for (String item : node1.set) {
						newIS.addItem(item);
					}
					newIS.addItem(word);
					DicHashTreeNode newNode = new DicHashTreeNode(i + 1, basketIndex);
					newIS.counter = 1;
					newNode.set = newIS;
					newNode.parent = node1;
					newNode.keyAtPArent = word;
					node1.put(word, newNode);

				}
			}
		}
	}
}
